import re

from django.contrib.auth import get_user_model
from django.contrib.auth.hashers import make_password
from django_redis import get_redis_connection
from rest_framework import serializers, status
from rest_framework.validators import UniqueValidator

from meiduo_mall_new.utils.reg import REGEX_MOBILE, REGEX_USERNAME, REGEX_EMAIL
from verifications import constants

User = get_user_model()


class ChekUsernameSerilizer(serializers.Serializer):
    """
     检验用户名序列化
    """
    username = serializers.CharField(required=True, min_length=6, max_length=11,
                                     error_messages={
                                         "min_length": "用户名最小长度不能小于6位",
                                         "min_length": "用户名最大长度不能超过11位",
                                         "required": "用户名不能为空"
                                     })

    def validate(self, attrs):
        username = attrs["username"] = attrs["username"].replace(" ", "")
        if username is None or username == "":
            raise serializers.ValidationError({"username": "用户名不能为空"}, 400)
        return attrs


class CheckMobileSerilizer(serializers.Serializer):
    """
    检验用户手机号序列化
    """

    mobile = serializers.CharField(required=True, min_length=11, max_length=11)

    def validate_mobile(self, mobile):
        if not re.match(REGEX_MOBILE, mobile):
            raise serializers.ValidationError("手机号非法")

        return mobile


class UserRegisterSerializer(serializers.ModelSerializer):
    """
    用户注册序列化
    """
    sms_code = serializers.CharField(required=True, write_only=True, max_length=6, min_length=6, error_messages={
        "blank": "请输入验证码",
        "required": "请输入验证码",
        "max_length": "验证码格式错误",
        "min_length": "验证码格式错误"
    })

    username = serializers.CharField(required=True, allow_blank=False,
                                     validators=[UniqueValidator(queryset=User.objects.all(), message="用户名已经存在")])

    mobile = serializers.CharField(required=True, allow_blank=False,
                                   validators=[
                                       UniqueValidator(queryset=User.objects.all(), message="该手机号已经注册过帐号，请直接登录")])

    password = serializers.CharField(write_only=True, required=True, allow_blank=False, min_length=6, max_length=11)

    def validate(self, attrs):
        mobile = attrs["mobile"]
        sms_code = attrs["sms_code"]
        username = attrs["username"]

        if not re.match(REGEX_USERNAME, username):
            raise serializers.ValidationError("帐号格式错误，4到11位（字母，数字，下划线，减号）")

        if not re.match(REGEX_MOBILE, mobile):
            raise serializers.ValidationError("手机号非法")

        redis_conn = get_redis_connection('verify_codes')
        sms_code_cache = redis_conn.get(constants.REGISTER_SMS_CODE + ":" + mobile)
        if sms_code_cache is None:
            raise serializers.ValidationError("验证码已经过期，请重新获取")
        else:
            if bytes.decode(sms_code_cache) != sms_code:
                raise serializers.ValidationError("验证码输入不正确，请重新输入")

        attrs["password"] = make_password(attrs["password"])
        attrs["nickname"] = attrs["username"]
        del attrs["sms_code"]
        return attrs

    class Meta:
        model = User
        fields = ("username", "password", "mobile", "sms_code")


class UserDetailSerializer(serializers.ModelSerializer):
    """
    用户详情序列化
    """

    class Meta:
        model = User
        fields = ("username", "nickname", "mobile", "email", "email_active")


class UserUpateSerializer(serializers.ModelSerializer):
    """
    更新用户信息序列化
    """
    nickname = serializers.CharField(required=True, min_length=4, max_length=11, allow_null=False, error_messages={
        "required": "昵称不允许为空",
        "allow_null": "昵称不允许为空"
    })
    email = serializers.CharField(required=True, allow_null=False, allow_blank=False, error_messages={
        "required": "邮箱不允许为空",
        "allow_null": "邮箱不允许为空",
        "allow_blank": "邮箱不允许为空"
    })
    email_active = serializers.BooleanField(read_only=True)

    def validate(self, attrs):
        user = self.context["request"].user
        email = attrs["email"]
        if not re.match(REGEX_EMAIL, email):
            raise serializers.ValidationError("邮箱格式错误，请重新输入")
        if email != user.email:
            # 修改了邮箱，发送邮件验证码，邮箱需要重新激活
            attrs["email_active"] = False

        return attrs

    class Meta:
        model = User
        fields = ("nickname", "email", "email_active")


class RestPwdSerializer(serializers.Serializer):
    password = serializers.CharField(required=True, allow_null=False, write_only=True)
    confirm_password = serializers.CharField(required=True, allow_null=False)
    sms_code = serializers.CharField(required=True, allow_null=False, min_length=6, max_length=6)
    access_token = serializers.CharField(required=True, allow_null=False)

    def validate(self, attrs):

        sms_code = attrs["sms_code"]
        access_token = attrs["access_token"]
        confirm_password = attrs['confirm_password']
        password = attrs['password']

        mobile = User.check_send_sms_code_token(access_token)

        if mobile is None:
            raise serializers.ValidationError("无效access token", status.HTTP_404_NOT_FOUND)

        redis_conn = get_redis_connection("verify_codes")
        real_sms_code = redis_conn.get(constants.FORGET_SMS_CODE + ":" + mobile)

        if real_sms_code is None:
            raise serializers.ValidationError("验证码已经过期，请重新获取")

        else:
            if bytes.decode(real_sms_code) != sms_code:
                raise serializers.ValidationError("验证码输入不正确，请重新输入")

        if confirm_password != password:
            raise serializers.ValidationError("两次密码不一致，请重新输入")

        attrs["mobile"] = mobile
        attrs["password"] = make_password(password)
        return attrs
